/**
 * @file main.c
 * @author 大傻猫二队
 * @brief 智能分类垃圾桶 AI 智慧视觉端
 * 
 * @copyright Copyright (c) 2023 大傻猫二队
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "sdk.h"

#include "defines.h"
#include "bsp.h"
#include "mpp.h"
#include "nnie.h"

int uart_fd;

static void signal_handler(int signo) {
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
    if (signo == SIGINT || signo == SIGTERM) {
        nnie_exit();
        mpp_exit();
        sdk_exit();
        bsp_exit();
        fprintf(stderr, "\033[0;31mProgram terminated abnormally!\033[0;39m\n");
    }
    exit(0);
}

// 按照深圳市垃圾分类标准, 可在国务院客户端小程序查询
// 0: 可回收物
// 1: 厨余垃圾
// 2: 有害垃圾
// 3: 其他垃圾
static int trash_type(int trash_class) {
    switch (trash_class) {
        case 1:  return 0; // 一次性快餐盒
        case 2:  return 0; // 书籍纸张
        case 3:  return 0; // 充电宝
        case 4:  return 1; // 剩饭剩菜
        case 5:  return 0; // 包
        case 6:  return 0; // 垃圾桶
        case 7:  return 0; // 塑料器皿
        case 8:  return 0; // 塑料玩具
        case 9:  return 0; // 塑料衣架
        case 10: return 3; // 大骨头 (小骨头才是厨余垃圾)
        case 11: return 2; // 干电池
        case 12: return 0; // 快递纸袋
        case 13: return 0; // 插头电线
        case 14: return 0; // 旧衣服
        case 15: return 0; // 易拉罐
        case 16: return 0; // 枕头
        case 17: return 1; // 果皮果肉
        case 18: return 0; // 毛绒玩具
        case 19: return 3; // 污损塑料
        case 20: return 3; // 污损用纸
        case 21: return 0; // 洗护用品
        case 22: return 3; // 烟蒂
        case 23: return 3; // 牙签
        case 24: return 0; // 玻璃器皿
        case 25: return 0; // 砧板
        case 26: return 0; // 筷子
        case 27: return 0; // 纸盒纸箱
        case 28: return 3; // 花盆
        case 29: return 1; // 茶叶渣
        case 30: return 1; // 菜帮菜叶
        case 31: return 1; // 蛋壳
        case 32: return 0; // 调料瓶
        case 33: return 2; // 软膏
        case 34: return 2; // 过期药物
        case 35: return 0; // 酒瓶
        case 36: return 0; // 金属厨具
        case 37: return 0; // 金属器皿
        case 38: return 0; // 金属食品罐
        case 39: return 0; // 锅
        case 40: return 3; // 陶瓷器皿
        case 41: return 0; // 鞋
        case 42: return 0; // 食用油桶
        case 43: return 0; // 饮料瓶
        case 44: return 1; // 鱼骨
        default: return 3;
    }
    return 0;
}

void nnie_callback(DetectObjInfo *detections, int count) {
    bool has_trash[4] = {false, false, false, false};
    for (int i = 0; i < count; i++) {
        int type = trash_type(detections[i].cls);
        has_trash[type] = true;
    }

    char buffer[5];
    int len = 0;
    for (int i = 0; i < 4; i++) {
        if (has_trash[i]) {
            buffer[len++] = '0' + i;
        }
    }
    buffer[len] = '\0';
    if (len > 0) {
        // LOG("Trash detection result: %s\n", buffer);
        uart_write(uart_fd, buffer, len);
    }
}

int main() {
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    bsp_init();
    uart_fd = uart_open(1);
    if (uart_fd < 0) {
        bsp_exit();
        exit(-1);
    }
    sdk_init();
    mpp_init();
    nnie_init();
    LOG("Smart trash bin has been started! Made by DLUT-DSM2ndTeam\n");

    char buffer[256];
    while (1) {
        int ret = uart_read(uart_fd, buffer, sizeof(buffer), 1000);
        if (ret > 0) {
            buffer[255] = 0;
            LOG("Received uart message: %s\n", buffer);
            if (buffer[0] == 'w') {
                nnie_start();
            } else if (buffer[0] == 's') {
                nnie_stop();
            } 
        }
    }

    return 0;
}
